MasterCamp TD9 & TD10 - Projet¶
-- Préparation des données --¶
Importation des librairies¶
In [1]:
%reset -f
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from sklearn.preprocessing import StandardScaler, MinMaxScaler, OneHotEncoder
from sklearn.cluster import KMeans
from sklearn.linear_model import LinearRegression
from sklearn.pipeline import Pipeline
from sklearn.compose import ColumnTransformer
from sklearn.model_selection import train_test_split
from sklearn.metrics import mean_absolute_error
import seaborn as sns
import geopandas as gpd
from kneed import KneeLocator
import geoviews as gv
from mpl_toolkits.mplot3d import Axes3D
gv.extension('bokeh')
Importation des données¶
In [2]:
# Chargement des données
df = 'data/valeursfoncieres-2023.txt'
# Lecture du fichier par échantillons de 10 000 lignes
df_chunks = pd.read_csv(df, sep='|', chunksize=10000, decimal=',')
# Concaténation des échantillons
df = pd.concat(df_chunks)
# On garde les colonnes qui nous intéressent :
df = df[["No disposition", "Date mutation", "Nature mutation", "Valeur fonciere", "Code departement", "Code commune", "Prefixe de section", "Section", "No plan", "Code type local", "Surface reelle bati", "Surface terrain", "Nombre pieces principales", "Surface Carrez du 1er lot", "Surface Carrez du 2eme lot", "Surface Carrez du 3eme lot", "Surface Carrez du 4eme lot", "Surface Carrez du 5eme lot"]]
# Afficher les 10 premières lignes
df.head(10)
Out[2]:
| No disposition | Date mutation | Nature mutation | Valeur fonciere | Code departement | Code commune | Prefixe de section | Section | No plan | Code type local | Surface reelle bati | Surface terrain | Nombre pieces principales | Surface Carrez du 1er lot | Surface Carrez du 2eme lot | Surface Carrez du 3eme lot | Surface Carrez du 4eme lot | Surface Carrez du 5eme lot | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 1 | 05/01/2023 | Vente | 1070000.0 | 1 | 354 | NaN | BD | 334 | 3.0 | 0.0 | NaN | 0.0 | NaN | NaN | NaN | NaN | NaN |
| 1 | 1 | 05/01/2023 | Vente | 1070000.0 | 1 | 354 | NaN | BD | 336 | 3.0 | 0.0 | NaN | 0.0 | NaN | NaN | NaN | NaN | NaN |
| 2 | 1 | 05/01/2023 | Vente | 1070000.0 | 1 | 354 | NaN | BD | 336 | 2.0 | 233.0 | NaN | 8.0 | NaN | NaN | NaN | NaN | NaN |
| 3 | 1 | 03/01/2023 | Vente | 152200.0 | 1 | 404 | NaN | D | 2317 | 1.0 | 64.0 | 988.0 | 3.0 | NaN | NaN | NaN | NaN | NaN |
| 4 | 1 | 05/01/2023 | Vente | 269000.0 | 1 | 361 | NaN | B | 2405 | 1.0 | 73.0 | 835.0 | 3.0 | NaN | NaN | NaN | NaN | NaN |
| 5 | 1 | 05/01/2023 | Vente | 269000.0 | 1 | 361 | NaN | B | 2405 | 3.0 | 0.0 | 835.0 | 0.0 | NaN | NaN | NaN | NaN | NaN |
| 6 | 1 | 05/01/2023 | Vente | 269000.0 | 1 | 361 | NaN | B | 2405 | 3.0 | 0.0 | 835.0 | 0.0 | NaN | NaN | NaN | NaN | NaN |
| 7 | 1 | 03/01/2023 | Vente | 770000.0 | 1 | 281 | NaN | AD | 41 | 1.0 | 136.0 | 921.0 | 7.0 | NaN | NaN | NaN | NaN | NaN |
| 8 | 1 | 06/01/2023 | Vente | 6820.0 | 1 | 446 | NaN | ZL | 19 | NaN | NaN | 17050.0 | NaN | NaN | NaN | NaN | NaN | NaN |
| 9 | 2 | 06/01/2023 | Echange | 10040.0 | 1 | 4 | NaN | AV | 900 | NaN | NaN | 124.0 | NaN | NaN | NaN | NaN | NaN | NaN |
Préparation des données¶
In [3]:
# Afficher les lignes du département 75
df[df['Code departement'] == '75'].head(10)
# Conversion des autres colonnes en types numériques, avec gestion des NaN
cols_to_convert = ['Surface reelle bati', 'Surface terrain']
for col in cols_to_convert:
df[col] = pd.to_numeric(df[col], errors='coerce')
# Remplacer les NaN par 0
df.fillna(0, inplace=True)
# Afficher les types de données
print(df.dtypes)
# Supprimer les lignes où la surface totale est nulle
df = df[df['Surface reelle bati'] > 0]
# Calculer le prix au mètre carré
df['Prix m2'] = df['Valeur fonciere'] / df['Surface reelle bati']
# Supprimer les lignes avec code type local = 0
df = df[df['Code type local'] != 0]
# Afficher les 10 premières lignes après nettoyage
print(df.head(10))
No disposition int64
Date mutation object
Nature mutation object
Valeur fonciere float64
Code departement object
Code commune int64
Prefixe de section float64
Section object
No plan int64
Code type local float64
Surface reelle bati float64
Surface terrain float64
Nombre pieces principales float64
Surface Carrez du 1er lot float64
Surface Carrez du 2eme lot float64
Surface Carrez du 3eme lot float64
Surface Carrez du 4eme lot float64
Surface Carrez du 5eme lot float64
dtype: object
No disposition Date mutation Nature mutation Valeur fonciere \
2 1 05/01/2023 Vente 1070000.0
3 1 03/01/2023 Vente 152200.0
4 1 05/01/2023 Vente 269000.0
7 1 03/01/2023 Vente 770000.0
14 3 06/01/2023 Vente 85520.0
16 1 04/01/2023 Vente 335000.0
17 1 04/01/2023 Vente 335000.0
20 1 04/01/2023 Vente 209000.0
22 1 03/01/2023 Vente 325000.0
29 1 04/01/2023 Vente 430000.0
Code departement Code commune Prefixe de section Section No plan \
2 1 354 0.0 BD 336
3 1 404 0.0 D 2317
4 1 361 0.0 B 2405
7 1 281 0.0 AD 41
14 1 24 0.0 AI 127
16 1 152 0.0 AC 166
17 1 152 0.0 AC 166
20 1 53 0.0 AC 528
22 1 348 0.0 YB 160
29 1 314 0.0 D 2776
Code type local Surface reelle bati Surface terrain \
2 2.0 233.0 0.0
3 1.0 64.0 988.0
4 1.0 73.0 835.0
7 1.0 136.0 921.0
14 1.0 160.0 0.0
16 1.0 106.0 1500.0
17 1.0 106.0 778.0
20 2.0 68.0 0.0
22 1.0 70.0 403.0
29 2.0 51.0 89.0
Nombre pieces principales Surface Carrez du 1er lot \
2 8.0 0.0
3 3.0 0.0
4 3.0 0.0
7 7.0 0.0
14 5.0 0.0
16 6.0 0.0
17 6.0 0.0
20 3.0 0.0
22 4.0 0.0
29 2.0 0.0
Surface Carrez du 2eme lot Surface Carrez du 3eme lot \
2 0.0 0.0
3 0.0 0.0
4 0.0 0.0
7 0.0 0.0
14 0.0 0.0
16 0.0 0.0
17 0.0 0.0
20 0.0 0.0
22 0.0 0.0
29 0.0 0.0
Surface Carrez du 4eme lot Surface Carrez du 5eme lot Prix m2
2 0.0 0.0 4592.274678
3 0.0 0.0 2378.125000
4 0.0 0.0 3684.931507
7 0.0 0.0 5661.764706
14 0.0 0.0 534.500000
16 0.0 0.0 3160.377358
17 0.0 0.0 3160.377358
20 0.0 0.0 3073.529412
22 0.0 0.0 4642.857143
29 0.0 0.0 8431.372549
Fusion des enregistrements de données similaires¶
In [4]:
# Fusionner les lignes similaires
df = df.groupby(['Date mutation', 'Valeur fonciere', 'Code departement', 'Code commune', 'Prefixe de section', 'Section', 'No plan', 'Surface terrain', 'Prix m2']).agg({
'Nombre pieces principales': 'sum',
'Code type local': 'min',
'Surface reelle bati': 'sum',
}).reset_index()
Filtering¶
In [5]:
# Calcul des quantiles et de l'InterQuartile Range (IQR)
Q1 = df[['Valeur fonciere', 'Surface reelle bati']].quantile(0.25) # récupérer les valeurs en dessous desquelles se trouvent 25% des données
Q3 = df[['Valeur fonciere', 'Surface reelle bati']].quantile(0.75) # récupérer les valeurs en dessous desquelles se trouvent 75% des données
IQR = Q3 - Q1 # la différence entre les deux quartiles représente la dispersion des données des 50% des données centrales
# Création du masque pour booléen pour filtrer les valeurs aberrantes (outliers)
mask_non_outliers = (
(df['Valeur fonciere'] >= (Q1['Valeur fonciere'] - 1.5 * IQR['Valeur fonciere'])) &
(df['Valeur fonciere'] <= (Q3['Valeur fonciere'] + 1.5 * IQR['Valeur fonciere'])) &
(df['Surface reelle bati'] >= (Q1['Surface reelle bati'] - 1.5 * IQR['Surface reelle bati'])) &
(df['Surface reelle bati'] <= (Q3['Surface reelle bati'] + 1.5 * IQR['Surface reelle bati']))
)
# Application du masque pour filtrer les valeurs non aberrantes
df_filtered = df[mask_non_outliers].copy()
-- Analyse exploratoire des données (EDA) --¶
Distribution de variables pour avoir une idée de la répartition des données avant Filtering et après Filtering¶
In [6]:
# Distribution de Valeur fonciere
plt.figure(figsize=(8, 6))
plt.hist(df['Valeur fonciere'], bins=20, color='skyblue')
plt.title('Distribution de Valeur fonciere')
plt.xlabel('Valeur fonciere')
plt.ylabel('Fréquence')
plt.show()
# Distribution de Code commune
plt.figure(figsize=(8, 6))
plt.hist(df['Code commune'], bins=20, color='skyblue')
plt.title('Distribution de Code commune')
plt.xlabel('Code commune')
plt.ylabel('Fréquence')
plt.show()
# Distribution de Code type local
plt.figure(figsize=(8, 6))
plt.hist(df['Code type local'], bins=20, color='skyblue')
plt.title('Distribution de Code type local')
plt.xlabel('Code type local')
plt.ylabel('Fréquence')
plt.show()
# Distribution de Surface reelle bati
plt.figure(figsize=(8, 6))
plt.hist(df['Surface reelle bati'], bins=20, color='skyblue')
plt.title('Distribution de Surface reelle bati')
plt.xlabel('Surface reelle bati')
plt.ylabel('Fréquence')
plt.show()
In [7]:
# Distribution par département
plt.figure(figsize=(25, 8))
# Assurer que 'Code departement' est une chaîne de caractères et trier
df_filtered['Code departement'] = df_filtered['Code departement'].astype(str)
# Renommer les départements pour ajouter un zéro devant les numéros à un chiffre
df_filtered['Code departement'] = df_filtered['Code departement'].apply(lambda x: x.zfill(2))
# Trier les départements par ordre croissant
df_filtered = df_filtered.sort_values('Code departement')
# Distribution de Valeur fonciere
plt.figure(figsize=(8, 6))
plt.hist(df_filtered['Valeur fonciere'], bins=20, color='lightcoral')
plt.title('Distribution de Valeur fonciere')
plt.xlabel('Valeur fonciere')
plt.ylabel('Fréquence')
plt.show()
# Distribution de Code commune
plt.figure(figsize=(8, 6))
plt.hist(df_filtered['Code commune'], bins=20, color='lightcoral')
plt.title('Distribution de Code commune')
plt.xlabel('Code commune')
plt.ylabel('Fréquence')
plt.show()
# Distribution de Code type local
plt.figure(figsize=(8, 6))
plt.hist(df_filtered['Code type local'], bins=20, color='lightcoral')
plt.title('Distribution de Code type local')
plt.xlabel('Code type local')
plt.ylabel('Fréquence')
plt.show()
# Distribution de Surface reelle bati
plt.figure(figsize=(8, 6))
plt.hist(df_filtered['Surface reelle bati'], bins=20, color='lightcoral')
plt.title('Distribution de Surface reelle bati')
plt.xlabel('Surface reelle bati')
plt.ylabel('Fréquence')
plt.show()
# Distribution par département
plt.figure(figsize=(20, 8))
# Assurer que 'Code departement' est une chaîne de caractères et trier
df_filtered['Code departement'] = df_filtered['Code departement'].astype(str)
df_filtered = df_filtered.sort_values('Code departement')
avg_price_by_type = df.groupby('Code type local')['Prix m2'].median().reset_index()
plt.figure(figsize=(10, 6))
sns.barplot(x='Code type local', y='Prix m2', data=avg_price_by_type, color='lightcoral')
plt.title('Prix moyen du mètre carré en fonction du type de propriété en 2023')
plt.xlabel('Code type local')
plt.ylabel('Prix par mètre carré en euros')
plt.legend(['1.0 : maison',
'2.0 : appartement',
'3.0 : dépendance',
'4.0 : local industriel'], loc = "upper left")
plt.show()
# Création du countplot pour afficher la distribution des transactions par département
sns.countplot(data=df_filtered, x='Code departement', palette='viridis')
plt.title('Distribution des transactions par département')
plt.xlabel('Code département')
plt.ylabel('Nombre de transactions')
plt.xticks(rotation=45)
plt.show()
<Figure size 2500x800 with 0 Axes>
<Figure size 2000x800 with 0 Axes>
C:\Users\Kevin\AppData\Local\Temp\ipykernel_12056\3885997085.py:66: FutureWarning: Passing `palette` without assigning `hue` is deprecated and will be removed in v0.14.0. Assign the `x` variable to `hue` and set `legend=False` for the same effect. sns.countplot(data=df_filtered, x='Code departement', palette='viridis')
Matrice de corrélation entre les variables¶
In [8]:
correlation_matrix = df_filtered[['Valeur fonciere', 'Nombre pieces principales', 'Code type local', 'Surface reelle bati', 'Prix m2']].corr()
plt.figure(figsize=(10, 8))
sns.heatmap(correlation_matrix, annot=True, cmap='Blues', vmin=-1, vmax=1)
plt.title('Matrice de corrélation entre les variables')
plt.show()
-- Machine Learning apprentissage non supervisé --¶
Clustering et visualisation¶
In [9]:
# On standardise les données
scaler = StandardScaler()
df_scaled = scaler.fit_transform(df[['Valeur fonciere', 'Surface reelle bati', 'Prix m2']])
# Décider du n-cluster avec la méthode Elbow
wcss = []
for n in range(1, 11):
kmeans = KMeans(n_clusters=n, random_state=42)
kmeans.fit(df_scaled)
wcss.append(kmeans.inertia_)
# Affichage du graphique Elbow
plt.figure(figsize=(8, 4))
plt.plot(range(1, 11), wcss, marker='o', color='darkcyan')
plt.title('Méthode Elbow pour déterminer le nombre optimal de clusters')
plt.xlabel('Nombre de clusters')
plt.ylabel('WCSS')
plt.show()
In [10]:
kl = KneeLocator(range(1, 11), wcss, curve="convex", direction="decreasing")
print(f'Le nombre optimal de clusters est {kl.elbow}')
Le nombre optimal de clusters est 5
Visualisation sans clustering et sans filtrage¶
In [11]:
# Afficher les données
sns.scatterplot(data=df, x='Surface reelle bati', y='Valeur fonciere', color='darkorange')
plt.show()
Visualisation avec clustering et sans filtrage¶
In [12]:
# Nombre optimal de clusters
optimal_clusters = kl.elbow
# Normalisation des données
scaler = StandardScaler()
df_scaled = scaler.fit_transform(df[['Surface reelle bati', 'Valeur fonciere', 'Prix m2']])
# Apprentissage K-Means
kmeans = KMeans(n_clusters=optimal_clusters, random_state=42)
clusters = kmeans.fit_predict(df_scaled)
# Ajout des clusters aux données d'origine
df['Cluster'] = clusters + 1
# Visualisation des clusters avec les centroïdes
plt.figure(figsize=(10, 6))
sns.scatterplot(data=df, x='Surface reelle bati', y='Valeur fonciere', hue='Cluster', palette='viridis')
# Ajouter les centroïdes
centroids = scaler.inverse_transform(kmeans.cluster_centers_)
plt.scatter(centroids[:, 0], centroids[:, 1], s=50, c='red', marker='X', edgecolors='black', label='Centroids')
plt.legend(loc='upper right')
plt.title('Clustering des biens immobiliers avec centroïdes')
plt.xlabel('Surface reelle bati')
plt.ylabel('Valeur fonciere')
plt.show()
Visualisation d'une boxplot pour détecter les valeurs aberrantes (outliers)¶
In [13]:
# Visualisation avec échelle logarithmique
plt.figure(figsize=(10, 6))
sns.boxplot(x=np.log10(df['Valeur fonciere'] + 1), color='plum')
plt.title('Boxplot des valeurs foncières (échelle logarithmique)')
plt.xlabel('Log10(Valeur fonciere)')
plt.show()
Visualisation avec clustering et avec filtrage¶
In [14]:
# Normalisation des données filtrées
scaler = StandardScaler()
df_scaled_filtered = scaler.fit_transform(df_filtered[['Valeur fonciere', 'Surface reelle bati', 'Prix m2']])
# Apprentissage K-Means avec le nombre de clusters optimal (5) sur les données filtrées
optimal_clusters = 5
kmeans_filtered = KMeans(n_clusters=optimal_clusters, random_state=42)
clusters_filtered = kmeans_filtered.fit_predict(df_scaled_filtered)
# Ajout des clusters aux données filtrées, ajustement pour commencer à 1
df_filtered['Cluster'] = clusters_filtered + 1
# Réduction de la densité des points pour une meilleure visualisation (prendre 0.2% des données)
df_sampled = df_filtered.sample(frac=0.002, random_state=42)
# Vérifiez la distribution des clusters après échantillonnage
print("Distribution des clusters après échantillonnage :")
print(df_sampled['Cluster'].value_counts())
# Créer une palette dynamique
unique_clusters = df_sampled['Cluster'].unique()
palette = sns.color_palette("tab10", len(unique_clusters))
# Visualisation des clusters sur les données filtrées (Valeur foncière en fonction de Surface)
plt.figure(figsize=(10, 6))
sns.scatterplot(data=df_sampled, x='Surface reelle bati', y='Valeur fonciere', hue='Cluster', palette=palette)
plt.title('Valeur foncière en fonction de Surface après suppression des valeurs aberrantes')
plt.xlabel('Surface reelle bati')
plt.ylabel('Valeur fonciere')
# Ajouter les centroïdes uniquement pour les clusters présents dans l'échantillon
centroids = scaler.inverse_transform(kmeans_filtered.cluster_centers_)
for i, cluster in enumerate(unique_clusters):
plt.scatter(centroids[cluster-1, 1], centroids[cluster-1, 0], s=100, c='red', marker='X', edgecolors='black')
plt.scatter([], [], s=100, c='red', marker='X', edgecolors='black', label='Centroids')
plt.legend(loc='upper right') # afficher la légende en haut à droite
plt.show()
Distribution des clusters après échantillonnage : Cluster 2 821 1 638 5 307 3 207 Name: count, dtype: int64
Visualisation des données par département et par cluster¶
In [15]:
# Assurer que 'Code departement' est une chaîne de caractères
df['Code departement'] = df['Code departement'].astype(str)
# Calcul des statistiques agrégées par département
df_dept_agg = df.groupby('Code departement').agg({
'Valeur fonciere': 'mean',
'Surface reelle bati': 'mean',
'Prix m2': 'mean'
}).reset_index()
# Standardisation des données agrégées
df_dept_agg_scaled = scaler.fit_transform(df_dept_agg[['Valeur fonciere', 'Surface reelle bati', 'Prix m2']])
# Appliquer le clustering
kmeans_dept = KMeans(n_clusters=5, random_state=42).fit(df_dept_agg_scaled)
df_dept_agg['Cluster'] = kmeans_dept.labels_ + 1 # Ajout de 1 pour que les clusters soient de 1 Ã 5
plt.figure(figsize=(12, 8))
sns.boxplot(data=df_dept_agg, x='Cluster', y='Valeur fonciere', hue='Cluster', palette='viridis', legend=False)
plt.title('Valeur foncière moyenne par cluster')
plt.xlabel('Cluster')
plt.ylabel('Valeur fonciere moyenne')
plt.show()
plt.figure(figsize=(12, 8))
sns.boxplot(data=df_dept_agg, x='Cluster', y='Surface reelle bati', hue='Cluster', palette='viridis', legend=False)
plt.title('Surface réelle bâtie moyenne par cluster')
plt.xlabel('Cluster')
plt.ylabel('Surface reelle bati moyenne')
plt.show()
plt.figure(figsize=(12, 8))
sns.boxplot(data=df_dept_agg, x='Cluster', y='Prix m2', hue='Cluster', palette='viridis', legend=False)
plt.title('Prix moyen par m2 par cluster')
plt.xlabel('Cluster')
plt.ylabel('Prix m2 moyen')
plt.show()
Geomap de la répartition du prix moyen par mètre carré par département¶
In [16]:
# Prix moyen du mètre carré par département
df['Prix_m2'] = df['Valeur fonciere'] / df['Surface reelle bati']
avg_price_per_department = df.groupby('Code departement')['Prix_m2'].median().reset_index()
# Charger les données géographiques
sf = gpd.read_file('france-geojson/departements-version-simplifiee.geojson')
# Correction pour s'assurer que les valeurs sont bien des chaînes de caractères
sf['code'] = sf['code'].astype(str).apply(lambda x: x.zfill(2) if x.isdigit() else x)
avg_price_per_department['Code departement'] = avg_price_per_department['Code departement'].astype(str).apply(lambda x: x.zfill(2) if x.isdigit() else x)
# Jointure des deux dataframes sur la colonne 'code' et 'Code departement'
df_merged = pd.merge(sf, avg_price_per_department[['Code departement', 'Prix_m2']], left_on='code', right_on='Code departement', how='left')
# Affichage du dataframe fusionné
print(df_merged.head())
# Visualisation avec Geoviews
deps = gv.Polygons(df_merged, vdims=['code','Prix_m2'])
from geoviews import dim
deps.opts(width=600, height=600, toolbar='above', color=dim('Prix_m2'),
colorbar=True , cmap = 'turbo', tools=['hover'], aspect='equal')
code nom \
0 01 Ain
1 02 Aisne
2 03 Allier
3 04 Alpes-de-Haute-Provence
4 05 Hautes-Alpes
geometry Code departement \
0 POLYGON ((4.78021 46.17668, 4.79458 46.21832, ... 01
1 POLYGON ((4.04797 49.40564, 4.03991 49.39740, ... 02
2 POLYGON ((3.03207 46.79491, 3.04907 46.75808, ... 03
3 POLYGON ((5.67604 44.19143, 5.69209 44.18648, ... 04
4 POLYGON ((6.26057 45.12685, 6.29922 45.10855, ... 05
Prix_m2
0 2608.695652
1 1339.155052
2 1279.534884
3 2402.439024
4 2815.000000
Out[16]:
In [17]:
# Affichage du prix moyen du mètre carré par département en 2023
plt.figure(figsize=(30, 6))
# Utilisation de colormap de seaborn pour colorer les barres en fonction de leur hauteur
norm = plt.Normalize(avg_price_per_department['Prix_m2'].min(), avg_price_per_department['Prix_m2'].max())
sm = plt.cm.ScalarMappable(cmap="jet", norm=norm)
sm.set_array([])
# Appliquer la colormap aux valeurs de 'Prix_m2'
colors = [sm.to_rgba(p) for p in avg_price_per_department['Prix_m2']]
# Création du barplot sans `hue` et en définissant manuellement les couleurs
barplot = sns.barplot(x='Code departement', y='Prix_m2', data=avg_price_per_department, palette=colors, dodge=False)
# Ajuster les étiquettes pour éviter le chevauchement
plt.gca().set_xticks(range(len(avg_price_per_department['Code departement'])))
plt.gca().set_xticklabels(avg_price_per_department['Code departement'], rotation=45)
# Ajout de la colorbar
cbar = plt.colorbar(sm, ax=barplot.figure.gca())
cbar.set_label('Prix par mètre carré (€)')
plt.title('Prix moyen du mètre carré par départements français en 2023')
plt.xlabel('Code département')
plt.ylabel('Prix par mètre carré (€)')
plt.show()
C:\Users\Kevin\AppData\Local\Temp\ipykernel_12056\1215888250.py:13: FutureWarning: Passing `palette` without assigning `hue` is deprecated and will be removed in v0.14.0. Assign the `x` variable to `hue` and set `legend=False` for the same effect. barplot = sns.barplot(x='Code departement', y='Prix_m2', data=avg_price_per_department, palette=colors, dodge=False)
-- Machine Learning apprentissage supervisé --¶
Régression Linéaire¶
Régression linéaire : Valeur foncière vs Surface reelle bati et Code département pour toutes les données¶
In [29]:
# Encodage one-hot pour la colonne 'Code departement'
encoder = OneHotEncoder()
column_transformer = ColumnTransformer(
[('encoder', encoder, ['Code departement'])],
remainder='passthrough'
)
# Création d'un pipeline avec le transformateur de colonnes et le modèle de régression linéaire
model = Pipeline(steps=[
('preprocessor', column_transformer),
('regressor', LinearRegression())
])
# Définition de X et y
X = df_filtered[['Surface reelle bati', 'Code departement']].copy()
y = df_filtered['Valeur fonciere'].copy()
# Normalisation de la caractéristique numérique 'Surface reelle bati'
scaler = MinMaxScaler()
X.loc[:, ['Surface reelle bati']] = scaler.fit_transform(X[['Surface reelle bati']])
# Ajustement du modèle
model.fit(X, y)
# Prédiction des valeurs
y_pred = model.predict(X)
# Calcul de l'erreur absolue moyenne
mae = mean_absolute_error(y, y_pred)
print("Mean Absolute Error:", mae)
print("Model Coefficients:", model.named_steps['regressor'].coef_)
# Échantillonnage d'une fraction des données pour l'affichage
sample_frac = 0.0005 # 0.05% des données
df_sampled = df_filtered.sample(frac=sample_frac, random_state=42)
# Prendre les indices des échantillons
sample_indices = df_sampled.index
# Extraire les valeurs échantillonnées de y et y_pred
y_sampled = y.loc[sample_indices]
y_pred_sampled = pd.Series(y_pred, index=y.index).loc[sample_indices]
# Affichage des résultats
plt.figure(figsize=(10, 6))
plt.scatter(df_sampled['Surface reelle bati'], y_sampled, color='blue', label='Actual Values', alpha=0.5)
plt.scatter(df_sampled['Surface reelle bati'], y_pred_sampled, color='red', label='Predicted Values', alpha=0.5)
plt.xlabel('Surface reelle bati')
plt.ylabel('Valeur foncière')
plt.title('Régression Linéaire: Valeur Foncière vs Surface reelle bati (échantillonnage)')
plt.legend(loc='best')
plt.show()
Mean Absolute Error: 81396.42900737676 Model Coefficients: [ 4.11377703e+04 -7.05050967e+04 -6.79092544e+04 1.73812816e+03 1.47642604e+04 1.02787436e+05 -7.57065601e+03 -6.72672527e+04 -5.36681167e+04 -4.65047134e+04 -2.83530003e+04 -4.70301186e+04 7.87781598e+04 2.26587053e+04 -6.91447529e+04 -5.11416047e+04 4.10219543e+04 -7.76459619e+04 -5.82937190e+04 -5.00885657e+03 -1.17111875e+04 -1.01260236e+05 -2.52911723e+04 -1.41249791e+04 2.06940793e+04 -1.01604088e+04 -1.97155194e+04 2.10937690e+03 7.66843727e+04 3.80706995e+04 2.65774798e+04 3.77449600e+04 -3.87103001e+04 7.56704604e+04 4.03495117e+04 3.24709461e+04 -8.69907617e+04 6.08323884e+03 3.33693416e+04 -3.49868749e+04 3.96612883e+04 -4.64711041e+04 -2.60321128e+04 -5.50769317e+04 6.10138157e+04 -1.92494803e+04 -3.39824460e+04 -4.27455281e+04 -4.15682959e+04 3.16020820e+03 -2.21137487e+04 -9.37333791e+03 -9.56645717e+04 -5.26315905e+04 -1.97182555e+04 -8.81508258e+04 3.16417851e+04 -8.33945203e+04 7.61491572e+01 1.06687362e+04 -5.83570765e+04 -2.17047246e+04 -2.84305759e+04 4.14662947e+04 -2.92945366e+04 4.15390045e+03 9.11346158e+04 -7.57188066e+04 -4.94405722e+04 -4.36813816e+04 6.28629791e+04 1.13523832e+05 1.95338470e+05 -4.87436238e+02 6.44204232e+04 1.08841142e+05 -6.70300513e+04 -2.72403014e+04 -3.08166554e+04 -2.06850788e+04 9.36117255e+04 4.49323372e+04 2.01017295e+04 -4.74981483e+04 -4.89570553e+04 -5.93737029e+04 -5.41284546e+04 -4.34121106e+04 7.47476379e+04 1.79240933e+05 9.40095338e+04 1.29728381e+05 8.45341318e+04 2.76556147e+04 1.78557769e+04 1.77573880e+04 3.05742511e+04 2.97351906e+05]
Régression linéaire avec ensemble d'entraînement et de test¶
In [31]:
# Définition du transformateur de colonnes avec un encodeur one-hot
encoder = OneHotEncoder()
column_transformer = ColumnTransformer(
[('encoder', encoder, ['Code departement'])],
remainder='passthrough'
)
# Création d'un pipeline avec le transformateur de colonnes et le modèle de régression linéaire
model = Pipeline(steps=[
('preprocessor', column_transformer),
('regressor', LinearRegression())
])
# Définition de X et y
X = df_filtered[['Surface reelle bati', 'Code departement']].copy()
y = df_filtered['Valeur fonciere'].copy()
# Normalisation de la caractéristique numérique 'Surface reelle bati'
scaler = MinMaxScaler()
X.loc[:, ['Surface reelle bati']] = scaler.fit_transform(X[['Surface reelle bati']])
# Fractionnement des données en ensembles d'entraînement et de test
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)
# Ajustement du modèle sur l'ensemble d'entraînement
model.fit(X_train, y_train)
# Prédiction des valeurs sur l'ensemble de test
y_pred = model.predict(X_test)
# Calcul de l'erreur absolue moyenne
mae = mean_absolute_error(y_test, y_pred)
print("Mean Absolute Error:", mae)
print("Model Coefficients:", model.named_steps['regressor'].coef_)
# Échantillonnage d'une fraction des données pour l'affichage
sample_frac = 0.0005 # 0.05% des données
X_test_sampled = X_test.sample(frac=sample_frac, random_state=42)
y_test_sampled = y_test.loc[X_test_sampled.index]
y_pred_sampled = pd.Series(y_pred, index=X_test.index).loc[X_test_sampled.index]
# Affichage des résultats
plt.figure(figsize=(10, 6))
plt.scatter(X_test_sampled['Surface reelle bati'], y_test_sampled, color='blue', label='Actual Values', alpha=0.5)
plt.scatter(X_test_sampled['Surface reelle bati'], y_pred_sampled, color='red', label='Predicted Values', alpha=0.5)
plt.xlabel('Surface reelle bati')
plt.ylabel('Valeur foncière')
plt.title('Régression Linéaire: Valeur Foncière vs Surface reelle bati (Ensemble de Test)')
plt.legend(loc='upper left') # Spécifier manuellement l'emplacement de la légende
plt.show()
Mean Absolute Error: 81383.25412149446 Model Coefficients: [ 4.08195619e+04 -6.93942411e+04 -6.74489845e+04 2.47113709e+03 1.42361436e+04 1.02389130e+05 -6.91956286e+03 -6.78092356e+04 -5.42304887e+04 -4.65070499e+04 -2.83574455e+04 -4.62637596e+04 7.83762487e+04 2.17339445e+04 -6.96823731e+04 -5.00629933e+04 4.20125276e+04 -7.76527970e+04 -5.77244206e+04 -5.05574520e+03 -1.18074427e+04 -1.00208707e+05 -2.59834435e+04 -1.47954481e+04 1.92737526e+04 -1.05844340e+04 -1.79488708e+04 1.80821205e+03 7.93744973e+04 3.63842990e+04 2.69995461e+04 3.73684087e+04 -4.04028613e+04 7.54550203e+04 4.10774799e+04 3.23876348e+04 -8.75041260e+04 7.70823153e+03 3.39112289e+04 -3.44401819e+04 3.94407035e+04 -4.59086059e+04 -2.68907604e+04 -5.54690438e+04 6.17031819e+04 -1.88969623e+04 -3.26827197e+04 -4.22103624e+04 -4.32122659e+04 2.13483992e+03 -2.26442865e+04 -9.15205276e+03 -9.52888946e+04 -5.38542277e+04 -1.93103171e+04 -8.84631379e+04 3.19322720e+04 -8.25017180e+04 -2.97700164e+02 1.07845385e+04 -5.98475733e+04 -2.16686318e+04 -2.86468934e+04 4.21416322e+04 -2.69875641e+04 4.01070018e+03 9.07827304e+04 -7.74241906e+04 -5.02388466e+04 -4.27400065e+04 6.11784232e+04 1.13402145e+05 1.96028199e+05 -2.19943010e+02 6.47726752e+04 1.09615510e+05 -6.69740940e+04 -2.72032696e+04 -3.03663356e+04 -1.80921442e+04 9.23627341e+04 4.50829725e+04 2.05970507e+04 -4.76206805e+04 -4.88132700e+04 -5.90413097e+04 -5.46537726e+04 -4.17404809e+04 7.43982213e+04 1.78592753e+05 9.38462736e+04 1.29520041e+05 8.51582693e+04 2.66947750e+04 1.83206563e+04 1.40025715e+04 2.95558004e+04 2.97640808e+05]
Régression Linéaire pour un département spécifique¶
Analyse avec plusieurs années¶
In [20]:
# Liste des chemins de fichiers
file_paths = [
"data/valeursfoncieres-2023.txt",
"data/valeursfoncieres-2022.txt",
"data/valeursfoncieres-2021.txt",
"data/valeursfoncieres-2020.txt",
"data/valeursfoncieres-2019.txt"
]
# Liste pour contenir les dataframes
dfs = []
# Lecture de chaque fichier par échantillons de 10 000 lignes et ajout du dataframe à la liste
for file_path in file_paths:
df_chunks = pd.read_csv(file_path, sep="|", chunksize=10000, decimal=",")
for chunk in df_chunks:
dfs.append(chunk)
# Combinaison de tous les morceaux en un seul DataFrame
multiple_time = pd.concat(dfs, ignore_index=True)
Filtering¶
In [21]:
# Suppression des lignes avec des valeurs NaN dans les colonnes spécifiées
multiple_time = multiple_time.dropna(subset=[
'Code departement', 'Code commune', 'Section',
'Date mutation', 'Valeur fonciere', 'Code type local'
])
# Conversion des autres colonnes en types numériques, avec gestion des NaN
cols_to_convert = ['Surface reelle bati', 'Surface terrain']
for col in cols_to_convert:
multiple_time[col] = pd.to_numeric(multiple_time[col], errors='coerce')
# Remplacer les NaN par 0
multiple_time.fillna(0, inplace=True)
# Afficher les types de données
print(multiple_time.dtypes)
# Supprimer les lignes où la surface totale est nulle
multiple_time = multiple_time[multiple_time['Surface reelle bati'] > 0]
# Fusionner les lignes similaires
multiple_time = multiple_time.groupby(['Date mutation', 'Valeur fonciere', 'Code departement', 'Code commune', 'Prefixe de section', 'Section']).agg({
'Code type local': 'min',
'Surface reelle bati': 'sum',
}).reset_index()
C:\Users\Kevin\AppData\Local\Temp\ipykernel_12056\1696940794.py:14: FutureWarning: Downcasting object dtype arrays on .fillna, .ffill, .bfill is deprecated and will change in a future version. Call result.infer_objects(copy=False) instead. To opt-in to the future behavior, set `pd.set_option('future.no_silent_downcasting', True)`
multiple_time.fillna(0, inplace=True)
Identifiant de document float64 Reference document float64 1 Articles CGI float64 2 Articles CGI float64 3 Articles CGI float64 4 Articles CGI float64 5 Articles CGI float64 No disposition int64 Date mutation object Nature mutation object Valeur fonciere float64 No voie float64 B/T/Q object Type de voie object Code voie object Voie object Code postal float64 Commune object Code departement object Code commune int64 Prefixe de section float64 Section object No plan int64 No Volume int64 1er lot object Surface Carrez du 1er lot float64 2eme lot object Surface Carrez du 2eme lot float64 3eme lot object Surface Carrez du 3eme lot float64 4eme lot object Surface Carrez du 4eme lot float64 5eme lot object Surface Carrez du 5eme lot float64 Nombre de lots int64 Code type local float64 Type local object Identifiant local float64 Surface reelle bati float64 Nombre pieces principales float64 Nature culture object Nature culture speciale object Surface terrain float64 dtype: object
In [22]:
# Calcul des quantiles et de l'InterQuartile Range (IQR)
Q1 = multiple_time[['Valeur fonciere', 'Surface reelle bati']].quantile(
0.25) # récupérer les valeurs en dessous desquelles se trouvent 25% des données
Q3 = multiple_time[['Valeur fonciere', 'Surface reelle bati']].quantile(
0.75) # récupérer les valeurs en dessous desquelles se trouvent 75% des données
IQR = Q3 - Q1 # la différence entre les deux quartiles représente la dispersion des données des 50% des données centrales
# Création du masque pour booléen pour filtrer les valeurs aberrantes (outliers)
mask_non_outliers = (
(multiple_time['Valeur fonciere'] >= (Q1['Valeur fonciere'] - 1.5 * IQR['Valeur fonciere'])) &
(multiple_time['Valeur fonciere'] <= (Q3['Valeur fonciere'] + 1.5 * IQR['Valeur fonciere'])) &
(multiple_time['Surface reelle bati'] >= (Q1['Surface reelle bati'] - 1.5 * IQR['Surface reelle bati'])) &
(multiple_time['Surface reelle bati'] <= (Q3['Surface reelle bati'] + 1.5 * IQR['Surface reelle bati']))
)
# Application du masque pour filtrer les valeurs non aberrantes
time_data = multiple_time[mask_non_outliers].copy()
print("Données chargées et combinées.")
print(time_data.head())
Données chargées et combinées.
Date mutation Valeur fonciere Code departement Code commune \
0 01/01/2019 80000.0 79 191
2 01/01/2019 167012.0 38 223
3 01/01/2019 180000.0 6 127
4 01/01/2019 382900.0 95 197
18 01/01/2020 87500.0 29 259
Prefixe de section Section Code type local Surface reelle bati
0 0.0 BW 2.0 96.0
2 0.0 D 2.0 73.0
3 0.0 C 2.0 113.0
4 0.0 AC 1.0 101.0
18 0.0 AM 2.0 62.0
Calcul de la valeur moyenne mensuelle¶
In [23]:
# Conversion de 'Date mutation' en format datetime
time_data['Date mutation'] = pd.to_datetime(time_data['Date mutation'], format='%d/%m/%Y')
# Calcul de la moyenne mensuelle de 'Valeur fonciere'
time_data['YearMonth'] = time_data['Date mutation'].dt.to_period('M')
monthly_avg = time_data.groupby('YearMonth')['Valeur fonciere'].mean().reset_index()
# Calcul du taux d'augmentation
monthly_avg['Valeur fonciere'] = monthly_avg['Valeur fonciere'].astype(float)
monthly_avg['Rate of Increase'] = monthly_avg['Valeur fonciere'].pct_change() * 100
# Affichage des résultats avec un axe y secondaire
fig, ax1 = plt.subplots(figsize=(12, 6))
# Affichage de la valeur moyenne sur l'axe y primaire
ax1.set_xlabel('Year-Month')
ax1.set_ylabel('Average Valeur Fonciere', color='blue')
ax1.plot(monthly_avg['YearMonth'].astype(str), monthly_avg['Valeur fonciere'], color='blue', marker='o', label='Average Valeur Fonciere')
ax1.tick_params(axis='y', labelcolor='blue')
ax1.legend(loc='upper left')
# Création d'un axe y secondaire pour le taux d'augmentation
ax2 = ax1.twinx()
ax2.set_ylabel('Rate of Increase (%)', color='red')
ax2.plot(monthly_avg['YearMonth'].astype(str), monthly_avg['Rate of Increase'], color='red', marker='x', label='Rate of Increase (%)')
ax2.tick_params(axis='y', labelcolor='red')
ax2.legend(loc='upper right')
# Titre et grille
plt.title('Monthly Average Valeur Fonciere and Rate of Increase Over Time')
fig.tight_layout()
plt.grid(True)
plt.xticks(rotation=45)
plt.show()
Régression Linéaire avec plusieurs années¶
In [24]:
# Conversion de 'Date mutation' en datetime
time_data['Date mutation'] = pd.to_datetime(time_data['Date mutation'], format='%d/%m/%Y')
# Conversion de 'Date mutation' en valeur numérique (jours depuis le début)
time_data['Date_numeric'] = (time_data['Date mutation'] - time_data['Date mutation'].min()).dt.days
# Vérification des valeurs uniques dans la colonne 'Code type local'
unique_code_type_local = time_data['Code type local'].unique()
print("Unique values in 'Code type local':", unique_code_type_local)
# Dictionnaire pour stocker les modèles
models = {}
# Boucle sur chaque 'Code type local' unique et création d'un graphique 3D
for specific_code_type_local in unique_code_type_local:
# Filtrer les données pour le 'Code type local' spécifique
filtered_data = time_data[time_data['Code type local'] == specific_code_type_local]
# Vérification du nombre d'échantillons dans les données filtrées pour le fractionnement
if len(filtered_data) < 2:
print(f"Not enough data points for Code type local: {specific_code_type_local}")
continue
# Fractionnement des données en ensembles d'entraînement et de test
X = filtered_data[['Surface reelle bati', 'Date_numeric']]
y = filtered_data['Valeur fonciere']
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)
scaler = MinMaxScaler()
X_train_scaled = scaler.fit_transform(X_train)
X_test_scaled = scaler.transform(X_test)
# Création et ajustement du modèle
model = LinearRegression()
model.fit(X_train_scaled, y_train)
# Stockage du modèle dans le dictionnaire
models[specific_code_type_local] = model
# Prédiction des valeurs
y_pred = model.predict(X_test_scaled)
# Calcul de l'erreur absolue moyenne
mae = mean_absolute_error(y_test, y_pred)
print(f"Code Type Local: {specific_code_type_local}")
print("Mean Absolute Error:", mae)
print("Model Coefficients:", model.coef_)
# Affichage des résultats en 3D
fig = plt.figure(figsize=(12, 8))
ax = fig.add_subplot(111, projection='3d')
ax.scatter(X_test['Surface reelle bati'], X_test['Date_numeric'], y_test, color='blue', label='Actual Values')
ax.scatter(X_test['Surface reelle bati'], X_test['Date_numeric'], y_pred, color='red', label='Predicted Values')
# Affichage du plan de régression
xx, yy = np.meshgrid(np.linspace(X_test['Surface reelle bati'].min(), X_test['Surface reelle bati'].max(), 10),
np.linspace(X_test['Date_numeric'].min(), X_test['Date_numeric'].max(), 10))
zz = model.coef_[0] * xx + model.coef_[1] * yy + model.intercept_
ax.plot_surface(xx, yy, zz, color='green', alpha=0.3)
ax.set_xlabel('Surface reelle bati')
ax.set_ylabel('Date (jours depuis le début)')
ax.set_zlabel('Valeur foncière')
ax.set_title(f'Régression Linéaire 3D pour le Code Type Local {specific_code_type_local}')
ax.legend(loc='upper left') # Spécifier manuellement l'emplacement de la légende
plt.show()
# Fonction pour prédire les valeurs en utilisant les modèles stockés
def predict_value(code_type_local, surface_reelle_bati, date_mutation):
if code_type_local not in models:
print(f"No model found for Code type local: {code_type_local}")
return None
model = models[code_type_local]
date_mutation = pd.to_datetime(date_mutation, format='%d/%m/%Y')
date_numeric = (date_mutation - time_data['Date mutation'].min()).days
prediction = model.predict([[surface_reelle_bati, date_numeric]])
return prediction[0]
# Exemple d'utilisation de la fonction de prédiction
example_code_type_local = unique_code_type_local[0]
example_surface_reelle_bati = 1000.0
example_date_mutation = '15/09/2023'
predicted_value = predict_value(example_code_type_local, example_surface_reelle_bati, example_date_mutation)
if predicted_value is not None:
print(f"Predicted Valeur Fonciere for Code type local {example_code_type_local} with Surface reelle bati {example_surface_reelle_bati} and Date Mutation {example_date_mutation}: {predicted_value}")
Unique values in 'Code type local': [2. 1. 4. 3.] Code Type Local: 2.0 Mean Absolute Error: 81244.83013934389 Model Coefficients: [215513.63958138 20480.60245359]
Code Type Local: 1.0 Mean Absolute Error: 89370.06087803903 Model Coefficients: [168922.84557839 33395.77420618]
Code Type Local: 4.0 Mean Absolute Error: 82326.41856892391 Model Coefficients: [128904.49755724 10453.87958864]
Not enough data points for Code type local: 3.0 Predicted Valeur Fonciere for Code type local 2.0 with Surface reelle bati 1000.0 and Date Mutation 15/09/2023: 250811481.0226707
Modèle de Valeur vs Surface pour tous les départements¶
In [25]:
# Vérification des valeurs uniques dans la colonne 'Code departement'
unique_code_departement = df_filtered['Code departement'].unique()
print("Unique values in 'Code departement':", unique_code_departement)
# Dictionnaire pour stocker les modèles
models = {}
# Boucle sur chaque 'Code departement' unique et création d'un graphique
for specific_code_departement in unique_code_departement:
# Filtrer les données pour le 'Code departement' spécifique
filtered_data = df_filtered[df_filtered['Code departement'] == specific_code_departement]
# Définition de X et y pour les données filtrées
X = filtered_data[['Surface reelle bati']]
y = filtered_data['Valeur fonciere']
# Fractionnement des données en ensembles d'entraînement et de test
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)
# Normalisation de la caractéristique numérique 'Surface reelle bati' en utilisant MinMaxScaler
scaler = MinMaxScaler()
X_train_scaled = scaler.fit_transform(X_train)
X_test_scaled = scaler.transform(X_test)
# Création et ajustement du modèle
model = LinearRegression()
model.fit(X_train_scaled, y_train)
# Stockage du modèle dans le dictionnaire
models[specific_code_departement] = model
# Prédiction des valeurs
y_pred = model.predict(X_test_scaled)
# Calcul de l'erreur absolue moyenne
mae = mean_absolute_error(y_test, y_pred)
print(f"Code Departement: {specific_code_departement}")
print("Mean Absolute Error:", mae)
print("Model Coefficients:", model.coef_)
# Affichage des résultats
plt.figure(figsize=(10, 6))
plt.scatter(X_test, y_test, color='blue', label='Actual Values')
plt.plot(X_test, y_pred, color='red', linewidth=2, label='Regression Line')
plt.xlabel('Surface reelle bati')
plt.ylabel('Valeur foncière')
plt.title(f'Régression Linéaire pour le Code Département {specific_code_departement}')
plt.legend()
plt.show()
# Fonction pour prédire les valeurs en utilisant les modèles stockés
def predict_value(code_departement, surface_reelle_bati):
if code_departement not in models:
print(f"No model found for Code departement: {code_departement}")
return None
model = models[code_departement]
surface_reelle_bati_scaled = scaler.transform([[surface_reelle_bati]])
prediction = model.predict(surface_reelle_bati_scaled)
return prediction[0]
# Exemple d'utilisation de la fonction de prédiction
example_code_departement = '1'
example_surface_reelle_bati = 1000.0
predicted_value = predict_value(example_code_departement, example_surface_reelle_bati)
if predicted_value is not None:
print(f"Predicted Valeur Fonciere for Code departement {example_code_departement} with Surface reelle bati {example_surface_reelle_bati}: {predicted_value}")
Unique values in 'Code departement': ['01' '02' '03' '04' '05' '06' '07' '08' '09' '10' '11' '12' '13' '14' '15' '16' '17' '18' '19' '21' '22' '23' '24' '25' '26' '27' '28' '29' '2A' '2B' '30' '31' '32' '33' '34' '35' '36' '37' '38' '39' '40' '41' '42' '43' '44' '45' '46' '47' '48' '49' '50' '51' '52' '53' '54' '55' '56' '58' '59' '60' '61' '62' '63' '64' '65' '66' '69' '70' '71' '72' '73' '74' '75' '76' '77' '78' '79' '80' '81' '82' '83' '84' '85' '86' '87' '88' '89' '90' '91' '92' '93' '94' '95' '971' '972' '973' '974'] Code Departement: 01 Mean Absolute Error: 97573.96816577067 Model Coefficients: [298202.36568187]
Code Departement: 02 Mean Absolute Error: 57774.78227954408 Model Coefficients: [154055.53114993]
Code Departement: 03 Mean Absolute Error: 63867.32195525461 Model Coefficients: [162846.66917832]
Code Departement: 04 Mean Absolute Error: 69619.51978815335 Model Coefficients: [354479.31576786]
Code Departement: 05 Mean Absolute Error: 72408.06356735145 Model Coefficients: [360568.17047314]
Code Departement: 06 Mean Absolute Error: 85263.39855744384 Model Coefficients: [561233.5094419]
Code Departement: 07 Mean Absolute Error: 77866.53405236678 Model Coefficients: [289646.81631582]
Code Departement: 08 Mean Absolute Error: 66542.69476648068 Model Coefficients: [138957.33902156]
Code Departement: 09 Mean Absolute Error: 59425.813226706894 Model Coefficients: [200844.3548776]
Code Departement: 10 Mean Absolute Error: 59108.82099391739 Model Coefficients: [191521.73639713]
Code Departement: 11 Mean Absolute Error: 67737.66596337958 Model Coefficients: [235989.27965852]
Code Departement: 12 Mean Absolute Error: 66731.44087917739 Model Coefficients: [203782.10564261]
Code Departement: 13 Mean Absolute Error: 93081.87452029945 Model Coefficients: [495590.98015543]
Code Departement: 14 Mean Absolute Error: 81415.92333969647 Model Coefficients: [261833.49278008]
Code Departement: 15 Mean Absolute Error: 61922.30508291257 Model Coefficients: [132776.70800924]
Code Departement: 16 Mean Absolute Error: 69721.19445636825 Model Coefficients: [162731.50375497]
Code Departement: 17 Mean Absolute Error: 98302.5852137911 Model Coefficients: [220214.47105388]
Code Departement: 18 Mean Absolute Error: 54524.28165776157 Model Coefficients: [196701.70041256]
Code Departement: 19 Mean Absolute Error: 63778.614892538084 Model Coefficients: [212544.51689069]
Code Departement: 21 Mean Absolute Error: 74716.29962379229 Model Coefficients: [261967.39267011]
Code Departement: 22 Mean Absolute Error: 80735.29693530935 Model Coefficients: [244141.91912562]
Code Departement: 23 Mean Absolute Error: 52248.85299677918 Model Coefficients: [117429.9780182]
Code Departement: 24 Mean Absolute Error: 76652.99477608912 Model Coefficients: [222668.46529536]
Code Departement: 25 Mean Absolute Error: 75202.20267461722 Model Coefficients: [261367.21473194]
Code Departement: 26 Mean Absolute Error: 83204.58607250637 Model Coefficients: [346780.24963628]
Code Departement: 27 Mean Absolute Error: 65376.58372666967 Model Coefficients: [244879.34564361]
Code Departement: 28 Mean Absolute Error: 64864.270328090955 Model Coefficients: [245061.63134228]
Code Departement: 29 Mean Absolute Error: 75110.34167934413 Model Coefficients: [297023.97747871]
Code Departement: 2A Mean Absolute Error: 105190.8668992282 Model Coefficients: [413350.09794148]
Code Departement: 2B Mean Absolute Error: 82567.54337048896 Model Coefficients: [434040.31196497]
Code Departement: 30 Mean Absolute Error: 85728.85188581907 Model Coefficients: [342048.48011371]
Code Departement: 31 Mean Absolute Error: 76029.2269648073 Model Coefficients: [390909.92054051]
Code Departement: 32 Mean Absolute Error: 74676.12390339887 Model Coefficients: [179682.52998141]
Code Departement: 33 Mean Absolute Error: 98258.95420376807 Model Coefficients: [309571.91583857]
Code Departement: 34 Mean Absolute Error: 81156.23739363955 Model Coefficients: [400158.02776177]
Code Departement: 35 Mean Absolute Error: 78453.00198676804 Model Coefficients: [302145.51062356]
Code Departement: 36 Mean Absolute Error: 52009.75402696208 Model Coefficients: [149353.33142052]
Code Departement: 37 Mean Absolute Error: 73838.95679691547 Model Coefficients: [296116.01615536]
Code Departement: 38 Mean Absolute Error: 77471.2400250184 Model Coefficients: [382580.40579423]
Code Departement: 39 Mean Absolute Error: 74020.4586187284 Model Coefficients: [184824.57962137]
Code Departement: 40 Mean Absolute Error: 90517.52643242406 Model Coefficients: [231488.60933651]
Code Departement: 41 Mean Absolute Error: 63442.01711360289 Model Coefficients: [199151.92428339]
Code Departement: 42 Mean Absolute Error: 77382.3750869417 Model Coefficients: [283095.51816146]
Code Departement: 43 Mean Absolute Error: 67792.1263241022 Model Coefficients: [189360.43973278]
Code Departement: 44 Mean Absolute Error: 82839.70055088743 Model Coefficients: [369680.51564943]
Code Departement: 45 Mean Absolute Error: 63761.57013625506 Model Coefficients: [243645.50959367]
Code Departement: 46 Mean Absolute Error: 72663.2692750348 Model Coefficients: [218222.67181156]
Code Departement: 47 Mean Absolute Error: 69758.28087195441 Model Coefficients: [198058.11227339]
Code Departement: 48 Mean Absolute Error: 72893.47032340906 Model Coefficients: [203100.82492619]
Code Departement: 49 Mean Absolute Error: 74128.46528960364 Model Coefficients: [237489.56473421]
Code Departement: 50 Mean Absolute Error: 76241.27859223472 Model Coefficients: [215478.80345317]
Code Departement: 51 Mean Absolute Error: 71934.87581358268 Model Coefficients: [234879.78749259]
Code Departement: 52 Mean Absolute Error: 59562.248189382866 Model Coefficients: [140338.81912802]
Code Departement: 53 Mean Absolute Error: 64940.70342618629 Model Coefficients: [148259.29999432]
Code Departement: 54 Mean Absolute Error: 74426.10835498426 Model Coefficients: [226901.9239969]
Code Departement: 55 Mean Absolute Error: 57000.19409377068 Model Coefficients: [113784.49024525]
Code Departement: 56 Mean Absolute Error: 93710.73484951763 Model Coefficients: [280625.72470909]
Code Departement: 58 Mean Absolute Error: 56106.681813696414 Model Coefficients: [150427.19965389]
Code Departement: 59 Mean Absolute Error: 83036.54730398337 Model Coefficients: [220943.18262733]
Code Departement: 60 Mean Absolute Error: 74619.59874925022 Model Coefficients: [265421.22839311]
Code Departement: 61 Mean Absolute Error: 64627.66849206918 Model Coefficients: [192916.15548678]
Code Departement: 62 Mean Absolute Error: 71204.30549244143 Model Coefficients: [181346.07045597]
Code Departement: 63 Mean Absolute Error: 70924.59580901738 Model Coefficients: [252971.07169622]
Code Departement: 64 Mean Absolute Error: 100127.84166173363 Model Coefficients: [241219.76968009]
Code Departement: 65 Mean Absolute Error: 69562.41336566169 Model Coefficients: [187382.7756784]
Code Departement: 66 Mean Absolute Error: 73093.15116022556 Model Coefficients: [359051.97478234]
Code Departement: 69 Mean Absolute Error: 91338.88636219315 Model Coefficients: [421797.05116845]
Code Departement: 70 Mean Absolute Error: 63238.83859876982 Model Coefficients: [154053.66872218]
Code Departement: 71 Mean Absolute Error: 65615.09504795955 Model Coefficients: [224951.86862932]
Code Departement: 72 Mean Absolute Error: 60448.06678200646 Model Coefficients: [215092.74309659]
Code Departement: 73 Mean Absolute Error: 94325.01266887758 Model Coefficients: [345523.08734429]
Code Departement: 74 Mean Absolute Error: 94242.73423405325 Model Coefficients: [468129.66590011]
Code Departement: 75 Mean Absolute Error: 114840.6518238581 Model Coefficients: [524444.10619982]
Code Departement: 76 Mean Absolute Error: 70131.48309984992 Model Coefficients: [277230.98330623]
Code Departement: 77 Mean Absolute Error: 77694.05739448582 Model Coefficients: [345280.49505839]
Code Departement: 78 Mean Absolute Error: 89586.92010737561 Model Coefficients: [412655.06249743]
Code Departement: 79 Mean Absolute Error: 61802.5318858593 Model Coefficients: [166046.54295125]
Code Departement: 80 Mean Absolute Error: 66255.26381679648 Model Coefficients: [164393.72318901]
Code Departement: 81 Mean Absolute Error: 72637.91303508163 Model Coefficients: [233424.4406442]
Code Departement: 82 Mean Absolute Error: 71426.5493490965 Model Coefficients: [212979.18717337]
Code Departement: 83 Mean Absolute Error: 93790.70002424659 Model Coefficients: [470459.47498879]
Code Departement: 84 Mean Absolute Error: 88850.71623207384 Model Coefficients: [403506.83334498]
Code Departement: 85 Mean Absolute Error: 78585.31715043787 Model Coefficients: [232389.8285705]
Code Departement: 86 Mean Absolute Error: 65864.09614315827 Model Coefficients: [181456.01527615]
Code Departement: 87 Mean Absolute Error: 66864.42088605031 Model Coefficients: [175593.03355251]
Code Departement: 88 Mean Absolute Error: 69399.34842612412 Model Coefficients: [150052.83925974]
Code Departement: 89 Mean Absolute Error: 60970.31315807626 Model Coefficients: [154555.37221685]
Code Departement: 90 Mean Absolute Error: 66220.59792582777 Model Coefficients: [234428.16118942]
Code Departement: 91 Mean Absolute Error: 75722.2148139991 Model Coefficients: [419069.93964039]
Code Departement: 92 Mean Absolute Error: 90289.2202917326 Model Coefficients: [638411.03435154]
Code Departement: 93 Mean Absolute Error: 84140.34401793324 Model Coefficients: [432278.71257903]
Code Departement: 94 Mean Absolute Error: 90024.70434550165 Model Coefficients: [494350.04042094]
Code Departement: 95 Mean Absolute Error: 75924.44658672833 Model Coefficients: [442024.7809435]
Code Departement: 971 Mean Absolute Error: 102121.35183744864 Model Coefficients: [256849.72610808]
Code Departement: 972 Mean Absolute Error: 91657.50363382907 Model Coefficients: [303247.05475501]
Code Departement: 973 Mean Absolute Error: 94426.63434582407 Model Coefficients: [176219.27791096]
Code Departement: 974 Mean Absolute Error: 87518.051793863 Model Coefficients: [365443.21030488]
No model found for Code departement: 1